import iconv from 'iconv-lite'
import { Buffer } from 'buffer'
import utils from '../utils'

function encodingIsUtf8(enc) {
  return !enc || /^utf-?8$/i.test(String(enc))
}
// Identify the most common encodings that are supersets of ascii at the
// single-byte level (meaning that bytes in 0 - 0x7f range must be ascii)
// (this allows identifying line breaks and other ascii patterns in buffers)
function encodingIsAsciiCompat(enc) {
  enc = standardizeEncodingName(enc)
  // gb.* selects the Guo Biao encodings
  // big5 in not compatible -- second byte starts at 0x40
  return !enc || /^(win|latin|utf8|ascii|iso88|gb)/.test(enc)
}
function standardizeEncodingName(enc) {
  return (enc || '').toLowerCase().replace(/[_-]/g, '')
}
function bufferToString(buf, enc, start, end) {
  if (start >= 0) {
    buf = buf.slice(start, end)
  }
  return decodeString(buf, enc)
}
function getNativeEncoder(enc) {
  let encoder = null;
  enc = standardizeEncodingName(enc)
  if (enc != 'utf8') {
    // TODO: support more encodings if TextEncoder is available
    return null
  }
  if (typeof TextEncoder != 'undefined') {
    encoder = new TextEncoder(enc)
  }
  return function(str) {
    // Convert Uint8Array from encoder to Buffer (fix for issue #216)
    return encoder ? Buffer.from(encoder.encode(str).buffer) : utils.createBuffer(str, enc)
  }
}
const encodeString = (function() {
  const toUtf8 = getNativeEncoder('utf8')
  return function(str, enc) {
    // TODO: faster ascii encoding?
    let buf = null
    if (encodingIsUtf8(enc)) {
      buf = toUtf8(str)
    } else {
      buf = iconv.encode(str, enc)
    }
    return buf
  }
}())
function getNativeDecoder(enc) {
  let decoder = null
  enc = standardizeEncodingName(enc)
  if (enc !== 'utf8') {
    return null
  }
  if (typeof TextDecoder !== 'undefined') {
    decoder = new TextDecoder(enc)
  }
  return (buf) => {
    return decoder ? decoder.decode(buf) : buf.toString(enc)
  }
}
function trimBOM(str) {
  // remove BOM if present
  if (str.charCodeAt(0) == 0xfeff) {
    str = str.substr(1)
  }
  return str
}
const decodeString = (function() {
  const fromUtf8 = getNativeDecoder('utf8')
  return function(buf, enc) {
    let str = ''
    if (encodingIsUtf8(enc)) {
      str = fromUtf8(buf)
    } else {
      str = iconv.decode(buf, enc)
    }
    return str
  }
}())
export default {
  encodingIsAsciiCompat,
  standardizeEncodingName,
  bufferToString,
  decodeString,
  encodeString,
  trimBOM,
}